#include <debug.h>
#include <isr.h>
#include <vga.h>
#include <mm.h>
#include <sched.h>
#include <i386.h>

/* Nombres de Excepciones */

char* exp_name[] =
{
    "Divide Error",
    "Debug Interrupt",
    "NMI Interrupt",
    "Breakpoint",
    "Interrupt On Overflow",
    "Bound Range Exceeded",
    "Invalid Opcode",
    "Device Not Available",
    "Double Fault",
    "Coprocessor Segment Overrun",
    "Invalid TSS",
    "Segment Not Present",
    "Stack Exception",
    "General Protection Fault",
    "Page Fault",
    "Reserved",
    "Floating Point Exception",
    "Alignment Check"
};

bool in_panic = FALSE;

void debug_kernelpanic(uint_32 index, uint_32 error_code, task_state *st)
{
    if (in_panic)
        while (1)
            ; /* Nothing */

    in_panic = TRUE;

    vga_set_char_color(WHITE);
    vga_set_scrn_color(RED);
    vga_clrscr();

    vga_set_cursor(1, 2);
    vga_printf("KERNEL PANIC!! - %s", exp_name[index]);
    vga_set_cursor(3, 2);
    vga_printf("Exception %2h - Error Code: %h", index , error_code);

    /* Registros */

    vga_set_cursor(5, 2);
    vga_printf("Registers:");
    
    vga_set_cursor(6, 2);
    vga_printf("EAX: %h", st->eax);
    vga_set_cursor(7, 2);
    vga_printf("EBX: %h", st->ebx);
    vga_set_cursor(8, 2);
    vga_printf("ECX: %h", st->ecx);
    vga_set_cursor(9, 2);
    vga_printf("EDX: %h", st->edx);
    vga_set_cursor(10, 2);
    vga_printf("ESI: %h", st->esi);
    vga_set_cursor(11, 2);
    vga_printf("EDI: %h", st->edi);
    vga_set_cursor(12, 2);
    vga_printf("EBP: %h", st->ebp);
    vga_set_cursor(13, 2);
    vga_printf("ESP: %h", st->esp);
    vga_set_cursor(14, 2);
    vga_printf("EIP: %h", st->eip);
    vga_set_cursor(15, 2);
    vga_printf("EFL: %h", st->eflags);

    /* Pila */

    uint_32 *stack_addr = (uint_32*) st->esp;
    uint_32 fila = 6;

    vga_set_cursor(5, 22);
    vga_printf("Stack:");

    for( ; fila <= 15; fila++)
    {
        vga_set_cursor(fila, 22);
        vga_printf("%h : %h %h %h %h", stack_addr, stack_addr[0], stack_addr[1], stack_addr[2], stack_addr[3]);
        stack_addr += 4;
    }

    /* Backtrace */

    vga_set_cursor(17, 2);
    vga_printf("Backtrace: Te lo debo... ");

    while(1)
        ; /* Nothing */
}

void debug_kernelpanic_custom(char* msg)
{
    vga_set_char_color(WHITE);
    vga_set_scrn_color(RED);
    vga_clrscr();

    vga_set_cursor(1, 2);
    vga_printf("KERNEL PANIC!! - %s", msg);

    while(1)
        ; /* Nothing */
}
